/*--------------------------------------------------------------*									   
 *--------------------------------------------------------------*/

#ifndef _FlashLogBuffManager_H_
#define _FlashLogBuffManager_H_

#include <stdint.h>
#include <stdlib.h>
#include "rtctime.h"
#include "flashtoeep.h"

// 内部 malloc 最大尺寸为 (sector_size 或 1024)|较大者
// 上电后第一次保存BUFF时，应检查是否与已存的最后一块数据一致，避免意外断电导致的的重复保存

/*--------------------------------------------ext Flash to Log Buffer--------------------------------------*/
typedef struct
{
	uint32_t flash_base;		/*当前基址*/
	uint32_t site_next;			/*指向当前待存储位置*/
	uint32_t sits_total;		/*分割块数*/
	uint16_t sits_per_sector;	
	uint16_t sits_per_extpage;
	uint16_t err;				/*上次错误代码*/
	uint16_t checked;			/*参数已经通过检测*/
} log_buff_info_type;


typedef struct
{
	uint16_t (*init)(void);
	uint16_t (*save)(void);
	uint16_t (*read)(uint32_t site, void *buff);
	uint16_t (*alain)(void);
	uint32_t (*site2addr)(uint32_t site);
	uint16_t (*head_search)(uint32_t num, uint32_t *site_des);
	int32_t (*time_search)(sig_time_type time, int8_t mode);
	int32_t (*time_quick_search)(sig_time_type time, int8_t mode);	// 仅用于未使用alain的bufff
}log_buff_api_type;

typedef struct
{
	uint32_t buff_amount;											/*缓存个数*/
	uint32_t first_base;											/*虚拟Eep基址  ,扇区边界对齐*/
	uint32_t buff_size;										  		/*总尺寸 2^n*/
	uint32_t sector_size;										 	/*buff扇区擦除尺寸 ,2^n */
	uint32_t ext_page_size;											/*外部存储器页尺寸，2^n 执行alain时按照此边界对齐，小于等于sector_size*/						   
	uint32_t data_size;										   		/*实际数据块尺寸,必须为4的倍数*/
	uint8_t *p_data;											   	/*数据源，应大于等于data_size*/
	log_buff_info_type *info;						   		 		/*运行时信息*/
	void (*erase)(uint32_t addr);									/*从指定地址擦除*/
	void (*program)(uint32_t addr, uint8_t *p_data, uint16_t Len); 	/*向指定指定地址编程数据*/
	void (*read)(uint32_t addr, uint8_t *p_data, uint16_t Len);		/*读取块数据*/
	void(*full_callback)(uint8_t mode);					  			/*存满回调 0-上电 1-Save 2-Alain*/
	const log_buff_api_type * api;									/*对象操作接口*/
} log_buff_cfg_type;

uint16_t log_buff_init(const log_buff_cfg_type *cfg);
uint16_t log_buff_save(const log_buff_cfg_type *cfg);
uint16_t log_buff_read(const log_buff_cfg_type *cfg, uint32_t site, void *buff);
uint16_t log_buff_align(const log_buff_cfg_type *cfg);
uint16_t log_buff_head_search(const log_buff_cfg_type *cfg, uint32_t num, uint32_t *site_des);	// 返回搜索到的个数，des指示结果相对位置
int32_t log_buff_time_search(const log_buff_cfg_type *cfg, sig_time_type time, int8_t mode);	// 搜索时间 ,返回值大于等于site_next说明没有结果
uint32_t log_buff_site2addr(const log_buff_cfg_type *cfg, uint32_t site);	// 相对于base的地址
/*-----------------------------------------------------------------------------------------------------*
 * 快速搜索，未使用对齐函数的连续数据
 * mode: 0(未命中目标时返回-1)，-1(未命中目标时返回小于目标值的位置)，1(未命中目标时返回大于目标值的位置)
 * return 返回-1代表未搜到指定结果， +数指向搜索结果位置
 *-----------------------------------------------------------------------------------------------------*/
int32_t log_buff_time_quick_search(const log_buff_cfg_type *cfg, sig_time_type time, int8_t mode);


/*-----------------------------------------------------------------------------------------------------*
* API
*-----------------------------------------------------------------------------------------------------*/
	#define log_buff_api_make(obj)											\
	uint16_t obj##_init(void){ return log_buff_init(&obj);}					\
	uint16_t obj##_save(void){ return log_buff_save(&obj);}					\
	uint16_t obj##_read(uint32_t site, void *buff)							\
		{ return log_buff_read(&obj, site, buff);}							\
	uint16_t obj##_alain(void ){ return log_buff_align(&obj);}				\
	uint32_t obj##_site2addr(uint32_t site)									\
		{ return log_buff_site2addr(&obj, site);}							\
	uint16_t obj##_head_search(uint32_t num, uint32_t *site_des)			\
		{ return log_buff_head_search(&obj, num, site_des);}				\
	int32_t obj##_time_search(sig_time_type time, int8_t mode)				\
		{ return log_buff_time_search(&obj, time, mode);}					\
	int32_t obj##_time_quick_search(sig_time_type time, int8_t mode)		\
		{ return log_buff_time_quick_search(&obj, time, mode);}				\
	const log_buff_api_type  obj##_api = {									\
		obj##_init,															\
		obj##_save,															\
		obj##_read,															\
		obj##_alain,														\
		obj##_site2addr,													\
		obj##_head_search,													\
		obj##_time_search,													\
		obj##_time_quick_search												\
	}
#define log_buff_api_ref(obj)	extern const log_buff_api_type obj##_api
#define log_buff_api_name(obj)	&obj##_api
	

#endif
